<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style type="text/css">
      #box1 {
        width: 300px;
        height: 300px;
        background-color: yellowgreen;
      }

      #box2 {
        width: 200px;
        height: 200px;
        background-color: yellow;
      }

      #box3 {
        width: 150px;
        height: 150px;
        background-color: skyblue;
      }
    </style>

    <script type="text/javascript">
      window.onload = function () {
        /* 
          分别为三个div绑定单击响应函数
        */
        var box1 = document.getElementById('box1');
        var box2 = document.getElementById('box2');
        var box3 = document.getElementById('box3');

        /* 
          事件的传播
            - 关于事件的传播网景公司和微软公司有不同的理解,不同的设计
            - 微软公司认为事件应该是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件。
                然后再向当前元素的祖先元素上传播,也就是说事件应该在冒泡阶段执行。
            - 网景公司认为事件应该是由外向内传播的,也就是当前事件触发时,
                应该先触发当前元素最外层的祖先元素的事件。
                然后在向内传播给后代元素。

            - W3C综合了俩个公司的方法,将事件传播分成了三个阶段
                1.捕获阶段
                  - 在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件。
                2.目标阶段
                  - 事件捕获到目标元素,捕获结束开始在目标元素上触发事件。
                3.冒泡阶段
                  - 事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件。
                
                - 如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true.
                  一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false.

            - IE8及以下的浏览器中没有捕获阶段。
        */

        bind(box1, 'click', function () {
          alert('我是box1的响应函数');
        });
        bind(box2, 'click', function () {
          alert('我是box2的响应函数');
        });
        bind(box3, 'click', function () {
          alert('我是box3的响应函数');
        });
      };

      /* 
          参数:
            obj 要绑定事件的对象
            eventStr 事件的字符串(不要on)
            callback 回调函数
        */
      function bind(obj, eventStr, callback) {
        if (obj.addEventListener) {
          //大部分浏览器兼容的方式
          obj.addEventListener(eventStr, callback, false);
        } else {
          /* 
              this是谁由调用方式决定
              callback.call(obj); 修改函数的this
            */
          //IE8及以下
          obj.attachEvent('on' + eventStr, function () {
            //在匿名函数中调用回调函数
            callback.call(obj);
          });
        }
      }
    </script>
  </head>
  <body>
    <div id="box1">
      <div id="box2">
        <div id="box3"></div>
      </div>
    </div>
  </body>
</html>
